package com.ilink.groundservice.service.impl.dataset;/**
 * <h3>iLink-java-backend-zhangbo2</h3>
 *
 * @Description <p>针对表【dataset_metadata】的服务实现类</p>
 * @Author ZhangBo
 * @Date 2024-09-15 20:39
 **/

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ilink.groundservice.entity.PO.dataset.DatasetMetadata;
import com.ilink.groundservice.entity.PO.dataset.DatasetTags;
import com.ilink.groundservice.entity.VO.dataset.DatasetResponse;
import com.ilink.groundservice.mapper.dataset.DatasetMetadataMapper;
import com.ilink.groundservice.service.dataset.DatasetMetadataService;
import com.ilink.groundservice.service.dataset.DatasetTagsService;
import com.ilink.ilinkapi.dto.ground.dataset.DatasetMetadataRequest;
import com.ilink.ilinkcommon.service.oss.OssService;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @ClassName DatasetMetadataServiceImpl
 * @Description 针对表【dataset_metadata】的服务实现类
 * @Author ZhangBo
 * @Date 2024-09-15 20:39
 **/
@Service
@Slf4j
@RequiredArgsConstructor
@CacheConfig(cacheNames = "dataset_metadata")
public class DatasetMetadataServiceImpl extends ServiceImpl<DatasetMetadataMapper, DatasetMetadata>
    implements DatasetMetadataService {

    private final DatasetTagsService datasetTagsService;
    private final OssService ossService;

    private final DatasetMetadataMapper datasetMetadataMapper;

    /**
     * @return com.baomidou.mybatisplus.core.metadata.IPage<com.ilink.groundservice.entity.VO.dataset.DatasetResponse>
     * @Author ZhangBo
     * @Description 分页查询数据广场元数据; 使用 redis 缓存
     * @Date 21:08 2024/9/15
     * @Param [sortBy, keywords, tag, page, size]
     **/
    @Override
    @Cacheable(key = "#request", unless = "#result == null")
    public IPage<DatasetResponse> getPublicDatasetMetadata(DatasetMetadataRequest request) {
        try {
            int page = request.getPage();
            int size = request.getSize();
            String keywords = request.getKeywords();
            String tag = request.getTag();
            String sortBy = request.getSortBy();

            LambdaQueryWrapper<DatasetMetadata> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DatasetMetadata::getAccessLevel, "public");

            // 关键词查询（注意判空）
            if (keywords != null && !keywords.isEmpty()) {
                // 获取与关键词匹配的所有 dataset_id
                List<Long> matchingDatasetIds = datasetTagsService.list(
                    new LambdaQueryWrapper<DatasetTags>().like(DatasetTags::getTag, keywords)
                ).stream().map(DatasetTags::getDatasetId).collect(Collectors.toList());

                // 如果存在匹配的 dataset_id，则加入查询条件
                if (!matchingDatasetIds.isEmpty()) {
                    lambdaQueryWrapper.and(wrapper -> wrapper
                        .like(DatasetMetadata::getName, keywords)
                        .or()
                        .like(DatasetMetadata::getDescription, keywords)
                        .or()
                        .in(DatasetMetadata::getDatasetId, matchingDatasetIds)
                    );
                } else {
                    // 如果没有匹配的 dataset_id，跳过 in 查询条件，仅对 name 和 description 进行匹配
                    lambdaQueryWrapper.and(wrapper -> wrapper
                        .like(DatasetMetadata::getName, keywords)
                        .or()
                        .like(DatasetMetadata::getDescription, keywords)
                    );
                }
            }

            // 标签查询
            if (tag != null && !tag.isEmpty()) {
                List<Long> datasetIdsWithTag = datasetTagsService.list(
                    new LambdaQueryWrapper<DatasetTags>().eq(DatasetTags::getTag, tag)
                ).stream().map(DatasetTags::getDatasetId).collect(Collectors.toList());

                if (!datasetIdsWithTag.isEmpty()) {
                    lambdaQueryWrapper.in(DatasetMetadata::getDatasetId, datasetIdsWithTag);
                } else {
                    return new Page<>(page, size); // Return empty result if no matching tags
                }
            }

            // Handle sorting
            if ("最热".equals(sortBy)) {
                lambdaQueryWrapper.orderByDesc(DatasetMetadata::getDownloadNum);
            } else if ("最新".equals(sortBy)) {
                lambdaQueryWrapper.orderByDesc(DatasetMetadata::getCreatedTime);
            }

            // Execute paginated query
            IPage<DatasetMetadata> datasetPage = this.page(new Page<>(page, size),
                lambdaQueryWrapper);

            // Convert DatasetMetadata to DatasetResponse
            List<DatasetResponse> datasetResponses = datasetPage.getRecords().stream()
                .map(dataset -> {
                    DatasetResponse response = new DatasetResponse();
                    response.setDatasetId(dataset.getDatasetId());
                    response.setName(dataset.getName());
                    response.setDescription(dataset.getDescription());
                    response.setCreatorName(dataset.getCreatorName());
                    response.setCreatedTime(dataset.getCreatedTime());
                    response.setAccessLevel(dataset.getAccessLevel());

                    String imageUrl = ossService.getImageUrl("dataset-square-migrate",
                        "image/" + dataset.getDatasetId());
                    response.setImagePath(imageUrl);
                    response.setUrl(dataset.getUrl());
                    response.setClickNum(dataset.getClickNum());
                    response.setDownloadNum(dataset.getDownloadNum());
                    response.setShareNum(dataset.getShareNum());
                    response.setFavoriteNum(dataset.getFavoriteNum());

                    List<String> tags = datasetTagsService.list(
                        new LambdaQueryWrapper<DatasetTags>().eq(DatasetTags::getDatasetId,
                            dataset.getDatasetId())
                    ).stream().map(DatasetTags::getTag).collect(Collectors.toList());
                    response.setTags(tags);

                    return response;
                }).collect(Collectors.toList());

            // Create the response page
            Page<DatasetResponse> datasetResponsePage = new Page<>(page, size);
            datasetResponsePage.setRecords(datasetResponses);
            datasetResponsePage.setTotal(datasetPage.getTotal());
            datasetResponsePage.setCurrent(datasetPage.getCurrent());
            datasetResponsePage.setSize(datasetPage.getSize());

            return datasetResponsePage;
        } catch (Exception e) {
            log.error("分页查询数据广场元数据服务错误" + e.getMessage());
            return null;
        }
    }

    /**
     * @return java.lang.String
     * @Author ZhangBo
     * @Description 增加数据集的download_num, 并且返回下载链接（公开数据集是直接跳转）
     * @Date 15:51 2024/9/16
     * @Param [targetId]
     **/
    @Override
    @Transactional
    public String downloadDataset(String targetId) {
        try {
            DatasetMetadata metadata = datasetMetadataMapper.selectById(targetId);
            if (metadata == null) {
                log.error("没有找到数据集" + targetId);
                return null;
            }
            Long downloadNum = metadata.getDownloadNum();
            metadata.setDownloadNum(downloadNum + 1);
            datasetMetadataMapper.updateById(metadata);
            return metadata.getUrl();
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * @return java.lang.String
     * @Author ZhangBo
     * @Description 增加数据集的share_num, 并且返回下载链接
     * @Date 15:51 2024/9/16
     * @Param [targetId]
     **/

    @Override
    @Transactional
    public String shareDataset(String targetId) {
        try {
            DatasetMetadata metadata = datasetMetadataMapper.selectById(targetId);
            if (metadata == null) {
                log.error("没有找到数据集" + targetId);
                return null;
            }
            Long shareNum = metadata.getShareNum();
            metadata.setShareNum(shareNum + 1);
            datasetMetadataMapper.updateById(metadata);
            return metadata.getUrl();
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * @return long
     * @Author ZhangBo
     * @Description 获取数据集数量
     * @Date 16:39 2024/9/16
     * @Param []
     **/
    @Override
    public long getDatasetMetadataCount() {
        // 使用 count 方法获取总数
        try {
            return datasetMetadataMapper.selectCount(null);
        } catch (Exception e) {
            log.error(e.getMessage());
            return 0;
        }
    }

    /**
     * @return com.ilink.groundservice.entity.VO.dataset.DatasetResponse
     * @Author ZhangBo
     * @Description 查找指定数据集元数据信息
     * @Date 16:58 2024/9/16
     * @Param [targetId]
     **/
    @Override
    public DatasetResponse getDatasetById(String targetId) {
        try {
            DatasetMetadata metadata = datasetMetadataMapper.selectById(targetId);
            if (metadata != null) {
                DatasetResponse response = new DatasetResponse();
                response.setDatasetId(Long.valueOf(targetId));
                response.setName(metadata.getName());

                List<String> tags = datasetTagsService.list(
                    new LambdaQueryWrapper<DatasetTags>()
                        .eq(DatasetTags::getDatasetId, targetId) // 使用 Lambda 表达式来指定字段
                ).stream().map(DatasetTags::getTag).collect(Collectors.toList());
                response.setTags(tags);
                response.setDescription(metadata.getDescription());
                response.setCreatorName(metadata.getCreatorName());
                response.setDownloadNum(metadata.getDownloadNum());
                response.setClickNum(metadata.getClickNum());
                response.setFavoriteNum(metadata.getFavoriteNum());
                response.setShareNum(metadata.getShareNum());
                response.setCreatedTime(metadata.getCreatedTime());

                String imageUrl = ossService.getImageUrl("dataset-square-migrate",
                    "image/" + targetId);
                response.setImagePath(imageUrl);
                response.setUrl(metadata.getUrl());
                return response;
            } else {
                log.error("未找到目标数据集");
                return null;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * @return java.lang.String
     * @Author ZhangBo
     * @Description 查找指定数据集文件
     * @Date 18:30 2024/9/16
     * @Param [targetId]
     **/
    @Override
    public String getDatasetsReadme(String targetId) {
        try {
            String datasetUrl = ossService.getBucketFileUrl("dataset-square-migrate",
                "readme/" + targetId + ".pdf");
            if (datasetUrl != null && !datasetUrl.isEmpty()) {
                return datasetUrl;
            }
            return null;
        } catch (Exception e) {
            log.error("函数getDatasetsReadme" + e.getMessage());
            return null;
        }
    }
}
